﻿using System;
using System.Diagnostics.Contracts;
using System.Net;
using System.Security.Principal;
using System.ServiceModel;
using System.Xml.Linq;
using System.Xml.XPath;
using SharePointContentGenerator.ContentGeneratorLogic.SharePointWebServiceCopy;
using SharePointContentGenerator.ContentGeneratorLogic.SharePointWebServiceLists;

namespace SharePointContentGenerator.ContentGeneratorLogic.Controllers
{
    internal abstract class SharePointController
    {
        internal TokenImpersonationLevel ImpersonationLevel { get; private set; }
        internal string Domain { get; private set; }
        internal string Username { get; private set; }
        internal string Password { get; private set; }
        internal string SiteCollection { get; private set; }

        internal SharePointController(string siteCollection)
        {
            Contract.Requires(siteCollection != null, "The site collection cannot be null");
            Contract.Requires(siteCollection != string.Empty, "The site collection cannot be string.empty");

            ImpersonationLevel = TokenImpersonationLevel.Impersonation;
            SiteCollection = GetWebServiceReference(siteCollection);
            Domain = string.Empty;
            Username = string.Empty;
            Password = string.Empty;
        }

        internal SharePointController(string siteCollection, string domain, string username, string password)
        {
            Contract.Requires(siteCollection != null, "The site collection cannot be null");
            Contract.Requires(siteCollection != string.Empty, "The site collection cannot be string.empty");
            Contract.Requires(domain != null, "The domain cannot be null");
            Contract.Requires(username != null, "The username cannot be null");
            Contract.Requires(password != null, "The password cannot be null");

            ImpersonationLevel = TokenImpersonationLevel.Impersonation;
            SiteCollection = GetWebServiceReference(siteCollection);
            Domain = domain.Trim();
            Username = username.Trim();
            Password = password.Trim();
        }

        protected ListsSoapClient GetListClient()
        {
            Contract.Requires(SiteCollection != null, "The site collection cannot be null");
            Contract.Requires(Username != null, "The username cannot be null");

            if (SiteCollection.Length > 0)
            {
                ListsSoapClient client = new ListsSoapClient();

                string webServiceLocation = string.Format("{0}/_vti_bin/Lists.asmx", SiteCollection);
                client.Endpoint.Address = new EndpointAddress(webServiceLocation);
                client.ClientCredentials.Windows.AllowedImpersonationLevel = ImpersonationLevel;

                if (Username.Length > 0)
                    client.ClientCredentials.Windows.ClientCredential = new NetworkCredential(Username, Password, Domain);

                return client;
            }
            else
                throw new InvalidOperationException("GetListClient: Site Collection has not been initialised");
        }

        protected CopySoapClient GetCopyclient()
        {
            Contract.Requires(SiteCollection != null, "The site collection cannot be null");
            Contract.Requires(Username != null, "The username cannot be null");

            if (SiteCollection.Length > 0)
            {
                CopySoapClient client = new CopySoapClient();

                string webServiceLocation = string.Format("{0}/_vti_bin/Copy.asmx", SiteCollection);
                client.Endpoint.Address = new EndpointAddress(webServiceLocation);
                client.ClientCredentials.Windows.AllowedImpersonationLevel = ImpersonationLevel;

                if (Username.Length > 0)
                    client.ClientCredentials.Windows.ClientCredential = new NetworkCredential(Username, Password, Domain);

                return client;
            }
            else
                throw new InvalidOperationException("GetCopyclient: Site Collection has not been initialised");
        }

        protected bool DoesListAlreadyExist(ListsSoapClient client, string listName)
        {
            bool alreadyExist = false;

            XElement result = client.GetListCollection();
            XPathNavigator navigator = result.CreateNavigator();
            XPathNodeIterator iterator = navigator.SelectDescendants("List", "http://schemas.microsoft.com/sharepoint/soap/", false);
            while (iterator.MoveNext())
            {
                string title = iterator.Current.GetAttribute("Title", string.Empty);
                if (title.Equals(listName))
                {
                    alreadyExist = true;
                    break;
                }
            }

            return alreadyExist;
        }

        private string GetWebServiceReference(string siteCollection)
        {
            Contract.Requires(siteCollection != null, "The site collection cannot be null");

            return siteCollection.EndsWith("/")
                ? siteCollection.Substring(0, siteCollection.Length - 1).Trim()
                : siteCollection.Trim();
        }
    }
}
